package com.tsy.server.wayline.controller;

import com.tsy.server.component.security.SecurityUtils;
import com.tsy.server.wayline.model.dto.WaylineFileDTO;
import com.tsy.server.wayline.service.IWaylineFileService;
import com.dji.sdk.cloudapi.device.DeviceEnum;
import com.dji.sdk.cloudapi.wayline.*;
import com.dji.sdk.cloudapi.wayline.api.IHttpWaylineService;
import com.dji.sdk.common.HttpResultResponse;
import com.dji.sdk.common.PaginationData;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * @author sean
 * @version 0.3
 * @date 2021/12/22
 */
@RestController
public class WaylineFileController implements IHttpWaylineService {

    @Autowired
    private IWaylineFileService waylineFileService;

    /**
     * 根据航线ID删除工作空间中的航线文件。
     * @param workspaceId 工作空间ID
     * @param waylineId 航线ID
     * @return
     */
    @ApiOperation("删除航线文件")
    @DeleteMapping("${url.wayline.prefix}/workspaces/{workspace_id}/waylines/{wayline_id}")
    public HttpResultResponse deleteWayline(@PathVariable(name = "workspace_id") String workspaceId,
                                            @PathVariable(name = "wayline_id") String waylineId) {
        boolean isDel = waylineFileService.deleteByWaylineId(workspaceId, waylineId);
        return isDel ? HttpResultResponse.success() : HttpResultResponse.error("Failed to delete wayline.");
    }

    /**
     * 导入 KMZ 航线文件。
     * @param file 上传的文件
     * @return
     */
    @ApiOperation("上传 KMZ 航线文件")
    @PostMapping("${url.wayline.prefix}/{project_id}/waylines/file/upload")
    public HttpResultResponse importKmzFile(MultipartFile file, @PathVariable("project_id") Long projectId) {
        if (Objects.isNull(file)) {
            return HttpResultResponse.error("请选择上传航线文件");
        }
        String creator = SecurityUtils.getCurrentUsername();
        String workspaceId = SecurityUtils.getWorkspaceId();
        waylineFileService.importKmzFile(file, workspaceId, projectId, creator);
        return HttpResultResponse.success();
    }

    /**
     * 根据查询条件查询航线文件的基础数据。
     * Pilot 端的查询条件字段是固定的。
     * @param request 查询参数
     * @param workspaceId 工作空间ID
     * @return
     */
    @ApiOperation("获取航线文件列表")
    @Override
    public HttpResultResponse<PaginationData<GetWaylineListResponse>> getWaylineList(@Valid GetWaylineListRequest request, String workspaceId, HttpServletRequest req, HttpServletResponse rsp) {
        PaginationData<GetWaylineListResponse> data = waylineFileService.getWaylinesByParam(workspaceId, request);
        return HttpResultResponse.success(data);
    }

    @ApiOperation("获取项目下的所有航线文件")
    @GetMapping("${url.wayline.prefix}/{project_id}/waylines")
    public HttpResultResponse<List<GetWaylineListResponse>> getProjectWaylines(@Valid GetWaylineListRequest request, @PathVariable("project_id") Long projectId) {
        List<GetWaylineListResponse> data = waylineFileService.getProjectWaylines(projectId, request);
        return HttpResultResponse.success(data);
    }

    /**
     * 根据航线文件ID查询文件下载地址，并直接重定向至该地址进行下载。
     * @param workspaceId 工作空间ID
     * @param waylineId 航线ID
     * @param req 请求
     * @param rsp 响应
     */
    @ApiOperation("获取航线文件下载地址")
    @Override
    public void getWaylineFileDownloadAddress(String workspaceId, String waylineId, HttpServletRequest req, HttpServletResponse rsp) {
        try {
            URL url = waylineFileService.getObjectUrl(workspaceId, waylineId);
            rsp.sendRedirect(url.toString());

        } catch (IOException | SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据航线名称检查是否已存在，必须保证航线名称唯一。
     * 上传航线时会调用此接口，必须可用。
     * @param workspaceId 工作空间ID
     * @param names 航线名称集合
     * @return
     */
    @ApiOperation("检查航线名称是否已存在")
    @Override
    public HttpResultResponse<List<String>> getDuplicatedWaylineName(String workspaceId, @NotNull @Size(min = 1) List<String> names, HttpServletRequest req, HttpServletResponse rsp) {
        List<String> existNamesList = waylineFileService.getDuplicateNames(workspaceId, names);

        return HttpResultResponse.success(existNamesList);
    }

    /**
     * 当 Pilot 将航线文件上传至存储服务后，通过此接口上报文件的基础信息。
     * @param request 上报请求
     * @param workspaceId 工作空间ID
     * @return
     */
    @ApiOperation("文件上传结果上报")
    @Override
    public HttpResultResponse fileUploadResultReport(String workspaceId, @Valid WaylineUploadCallbackRequest request, HttpServletRequest req, HttpServletResponse rsp) {

        WaylineUploadCallbackMetadata metadata = request.getMetadata();

        WaylineFileDTO file = WaylineFileDTO.builder()
                .username(SecurityUtils.getCurrentUsername())
                .objectKey(request.getObjectKey())
                .name(request.getName())
                .templateTypes(metadata.getTemplateTypes().stream().map(WaylineTypeEnum::getValue).collect(Collectors.toList()))
                .payloadModelKeys(metadata.getPayloadModelKeys().stream().map(DeviceEnum::getDevice).collect(Collectors.toList()))
                .droneModelKey(metadata.getDroneModelKey().getDevice())
                .build();

        // todo 需要将工作空间ID改为项目ID
        Long projectId = 0L;
        int id = waylineFileService.saveWaylineFile(workspaceId, projectId, file);

        return id <= 0 ? HttpResultResponse.error() : HttpResultResponse.success();
    }

    /**
     * 根据航线文件ID收藏航线文件。
     * @param workspaceId 工作空间ID
     * @param ids 航线文件ID集合
     * @return
     */
    @Override
    public HttpResultResponse batchFavoritesWayline(String workspaceId, @NotNull @Size(min = 1) List<String> ids, HttpServletRequest req, HttpServletResponse rsp) {
        boolean isMark = waylineFileService.markFavorite(workspaceId, ids, true);

        return isMark ? HttpResultResponse.success() : HttpResultResponse.error();
    }

    /**
     * 取消收藏：根据航线文件ID删除收藏记录。
     * @param workspaceId 工作空间ID
     * @param ids 航线文件ID集合
     * @return
     */
    @Override
    public HttpResultResponse batchUnfavoritesWayline(String workspaceId, @NotNull @Size(min = 1) List<String> ids, HttpServletRequest req, HttpServletResponse rsp) {
        boolean isMark = waylineFileService.markFavorite(workspaceId, ids, false);

        return isMark ? HttpResultResponse.success() : HttpResultResponse.error();
    }
}
